package com.unity.bh3.netty;

import com.alibaba.fastjson2.JSON;
import com.unity.bh3.manager.ChatRoomManager;
import com.unity.bh3.model.ChatMessage;
import com.unity.bh3.service.FriendService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.channel.ChannelHandler.Sharable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.HashMap;
import com.alibaba.fastjson2.JSONObject;

@Slf4j
@Component
@Sharable
public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Autowired
    private ChatRoomManager chatRoomManager;

    @Autowired
    private FriendService friendService;

    @Autowired
    private WebSocketManager webSocketManager;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
        Channel channel = ctx.channel();
        String text = frame.text();
        log.info("收到消息: {}", text);
        
        try {
            WebSocketMessage message = JSON.parseObject(text, WebSocketMessage.class);
            
            switch (message.getType()) {
                case "ROOM_CHANGE":
                    handleRoomChange(channel, message);
                    break;
                case "CHAT":
                    handleChat(channel, message);
                    break;
                case "USER_LOGIN":
                    handleUserLogin(channel, message);
                    break;
                case "FRIEND_REQUEST":
                    handleFriendRequest(channel, message);
                    break;
                case "FRIEND_REQUEST_RESPONSE":
                    handleFriendRequestResponse(channel, message);
                    break;
                case "FRIEND_MESSAGE":
                    handleFriendMessage(channel, message);
                    break;
                default:
                    log.warn("未知的消息类型: {}", message.getType());
            }
        } catch (Exception e) {
            log.error("处理消息时发生错误: ", e);
            /*WebSocketMessage errorMessage = WebSocketMessage.builder()
                    .type("ERROR")
                    .data("消息格式错误。请使用正确的格式：\n" +
                          "1. 用户登录：{\"type\":\"USER_LOGIN\",\"data\":2}\n" +
                          "2. 加入房间：{\"type\":\"ROOM_CHANGE\",\"data\":{\"roomId\":\"40\",\"userId\":2}}\n" +
                          "3. 发送消息：{\"type\":\"CHAT\",\"data\":{\"content\":\"hello\"}}\n" +
                          "4. 发送好友申请：{\"type\":\"FRIEND_REQUEST\",\"data\":{\"fromUserId\":1,\"toUserId\":2}}\n" +
                          "5. 处理好友申请：{\"type\":\"FRIEND_REQUEST_RESPONSE\",\"data\":{\"userId\":2,\"friendId\":1,\"accept\":true}}\n" +
                          "6. 发送好友消息：{\"type\":\"FRIEND_MESSAGE\",\"data\":{\"senderId\":1,\"receiverId\":2,\"content\":\"你好！\"}}")
                    .build();
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(errorMessage)));*/
        }
    }

    private void handleRoomChange(Channel channel, WebSocketMessage message) {
        try {
            Map<String, Object> data = JSON.parseObject(JSON.toJSONString(message.getData()), Map.class);
            String roomId = data.get("roomId") != null ? data.get("roomId").toString() : null;
            Long userId = data.get("userId") != null ? Long.valueOf(data.get("userId").toString()) : null;
            
            if (roomId == null || userId == null) {
                WebSocketMessage errorMessage = WebSocketMessage.builder()
                        .type("ERROR")
                        .data("房间ID和用户ID不能为空。正确格式：{\"type\":\"ROOM_CHANGE\",\"data\":{\"roomId\":\"40\",\"userId\":2}}")
                        .build();
                channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(errorMessage)));
                return;
            }
            
            chatRoomManager.joinRoom(roomId, userId.toString(), channel);
        } catch (Exception e) {
            /*log.error("处理房间变更消息时发生错误: ", e);
            WebSocketMessage errorMessage = WebSocketMessage.builder()
                    .type("ERROR")
                    .data("房间变更消息格式错误。正确格式：{\"type\":\"ROOM_CHANGE\",\"data\":{\"roomId\":\"40\",\"userId\":2}}")
                    .build();
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(errorMessage)));*/
        }
    }

    private void handleUserLogin(Channel channel, WebSocketMessage message) {
        try {
            Long userId = Long.valueOf(message.getData().toString());
            webSocketManager.addChannel(userId, channel);
            friendService.updateUserStatus(userId, true);
        } catch (Exception e) {
           /* log.error("处理用户登录消息时发生错误: ", e);
            WebSocketMessage errorMessage = WebSocketMessage.builder()
                    .type("ERROR")
                    .data("用户登录消息格式错误。正确格式：{\"type\":\"USER_LOGIN\",\"data\":2}")
                    .build();
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(errorMessage)));*/
        }
    }

    private void handleChat(Channel channel, WebSocketMessage message) {
        try {
            Map<String, Object> data = JSON.parseObject(JSON.toJSONString(message.getData()), Map.class);
            String content = (String) data.get("content");
            
            if (content == null) {
                WebSocketMessage errorMessage = WebSocketMessage.builder()
                        .type("ERROR")
                        .data("消息内容不能为空。正确格式：{\"type\":\"CHAT\",\"data\":{\"content\":\"hello\"}}")
                        .build();
                channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(errorMessage)));
                return;
            }
            
            chatRoomManager.sendChatMessage(channel, content);
        } catch (Exception e) {
            log.error("处理聊天消息时发生错误: ", e);
          /*  WebSocketMessage errorMessage = WebSocketMessage.builder()
                    .type("ERROR")
                    .data("聊天消息格式错误。正确格式：{\"type\":\"CHAT\",\"data\":{\"content\":\"hello\"}}")
                    .build();
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(errorMessage)));*/
        }
    }

    private void handleFriendRequest(Channel channel, WebSocketMessage message) {
        try {
            Map<String, Object> data = JSON.parseObject(JSON.toJSONString(message.getData()), Map.class);
            Long fromUserId = Long.valueOf(data.get("fromUserId").toString());
            Long toUserId = Long.valueOf(data.get("toUserId").toString());
            friendService.sendFriendRequest(fromUserId, toUserId);
        } catch (Exception e) {
            log.error("处理好友申请消息时发生错误: ", e);
       /*     WebSocketMessage errorMessage = WebSocketMessage.builder()
                    .type("ERROR")
                    .data(e)
                    .build();
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(errorMessage)));*/
        }
    }

    private void handleFriendRequestResponse(Channel channel, WebSocketMessage message) {
        try {
            Map<String, Object> data = JSON.parseObject(JSON.toJSONString(message.getData()), Map.class);
            Long userId = Long.valueOf(data.get("userId").toString());
            Long friendId = Long.valueOf(data.get("friendId").toString());
            boolean accept = (boolean) data.get("accept");
            friendService.handleFriendRequest(userId, friendId, accept);
        } catch (Exception e) {
            log.error("处理好友申请响应消息时发生错误: ", e);
           /* WebSocketMessage errorMessage = WebSocketMessage.builder()
                    .type("ERROR")
                    .data(e)
                    .build();
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(errorMessage)));*/
        }
    }

    private void handleFriendMessage(Channel channel, WebSocketMessage message) {
        try {
            Map<String, Object> data = JSON.parseObject(JSON.toJSONString(message.getData()), Map.class);
            Long senderId = Long.valueOf(data.get("senderId").toString());
            Long receiverId = Long.valueOf(data.get("receiverId").toString());
            String content = (String) data.get("content");
            friendService.sendMessage(senderId, receiverId, content);
        } catch (Exception e) {
            log.error("处理好友消息时发生错误: ", e);
          /*  WebSocketMessage errorMessage = WebSocketMessage.builder()
                    .type("ERROR")
                    .data("好友消息格式错误。正确格式：{\"type\":\"FRIEND_MESSAGE\",\"data\":{\"senderId\":1,\"receiverId\":2,\"content\":\"你好！\"}}")
                    .build();
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(errorMessage)));*/
        }
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        Channel channel = ctx.channel();
        log.info("新的WebSocket连接建立: {}", channel.remoteAddress());
        
        WebSocketMessage welcome = WebSocketMessage.builder()
                .type("CONNECT")
                .data("连接成功！请发送USER_LOGIN消息进行登录")
                .build();
        channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(welcome)));
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        Channel channel = ctx.channel();
        // 处理用户离线
        for (Map.Entry<Long, Channel> entry : webSocketManager.getUserChannels().entrySet()) {
            if (entry.getValue() == channel) {
                Long userId = entry.getKey();
                webSocketManager.removeChannel(userId);
                friendService.updateUserStatus(userId, false);
                break;
            }
        }
        chatRoomManager.leaveRoom(channel);
        log.info("客户端断开连接: {}", channel.remoteAddress());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("WebSocket错误: ", cause);
        ctx.close();
    }
} 